package com.gusto.engine.clusterant.algorithms.antsclustering.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.gusto.engine.clusterant.algorithms.antsclustering.AntsClusteringAlgorithmListener;
import com.gusto.engine.clusterant.algorithms.antsclustering.ants.Ant;
import com.gusto.engine.clusterant.algorithms.antsclustering.ants.AntRandom;
import com.gusto.engine.clusterant.algorithms.antsclustering.impl.thread.AntThread;
import com.gusto.engine.clusterant.algorithms.antsclustering.impl.thread.AntThreadListener;

/**
 * <p>Random Ants implementation, using {@link AntRandom}.</p>
 * 
 * @author amokrane.belloui@gmail.com
 *
 */
public class RandomAntsClusteringAlgorithm extends GenericAntsClusteringAlgorithm implements AntThreadListener {
	
	private Logger log = Logger.getLogger(getClass());
	
	private Integer ANTS = 1;
	private Long MOVES = 10000L;
	private Integer MAXMOVESWITHOBJECT = 100;
	private Double THRESHOLD_PICK = 0.2;
	private Double THRESHOLD_DROP = 0.2;
	private Integer PERCEPTION = 2;
	
	protected List<AntsClusteringAlgorithmListener> listeners = new ArrayList<AntsClusteringAlgorithmListener>();
	
	public Integer getANTS() {
		return ANTS;
	}

	public void setANTS(Integer ants) {
		ANTS = ants;
	}

	public Long getMOVES() {
		return MOVES;
	}

	public void setMOVES(Long moves) {
		MOVES = moves;
	}

	public Integer getMAXMOVESWITHOBJECT() {
		return MAXMOVESWITHOBJECT;
	}

	public void setMAXMOVESWITHOBJECT(Integer maxmoveswithobject) {
		MAXMOVESWITHOBJECT = maxmoveswithobject;
	}

	public Double getTHRESHOLD_PICK() {
		return THRESHOLD_PICK;
	}

	public void setTHRESHOLD_PICK(Double threshold_pick) {
		THRESHOLD_PICK = threshold_pick;
	}

	public Double getTHRESHOLD_DROP() {
		return THRESHOLD_DROP;
	}

	public void setTHRESHOLD_DROP(Double threshold_drop) {
		THRESHOLD_DROP = threshold_drop;
	}

	public Integer getPERCEPTION() {
		return PERCEPTION;
	}

	public void setPERCEPTION(Integer perception) {
		PERCEPTION = perception;
	}
	
	public List<AntsClusteringAlgorithmListener> getListeners() {
		return listeners;
	}
	
	public void setListeners(List<AntsClusteringAlgorithmListener> listeners) {
		this.listeners = listeners;
	}
	
	protected void doCluster() {
		log.info("Run ants classification");
		for (int i=0; i<ANTS; i++) {
			doAddAnt();
		}
	}
	
	public void doAddAnt() {
		log.info("Adding a new Ant");
		
		Ant ant = new AntRandom(plan, MOVES, MAXMOVESWITHOBJECT, THRESHOLD_PICK, THRESHOLD_DROP);
		ant.setPerception(PERCEPTION);
		ants.add(ant);
		
		if (listeners != null) {
			for (AntsClusteringAlgorithmListener listener : listeners) {
				listener.antAdded(ant);
			}
		}
		
		AntThread antThread = new AntThread(ant, (AntThreadListener)this);
		antThread.start();
	}
	
	public void jobFinished(Ant ant) {
		if (isAllAntsFinishedWork(ants)) {
			end = System.currentTimeMillis();
			log.info("Clustering done in " + (getTotalTime()) + " millis");
			log.info("Plan " + plan);
			for (Ant a : ants) {
				log.info(a);
			}
			if (listeners != null) {
				for (AntsClusteringAlgorithmListener listener : listeners) {
					listener.clusteringFinished(plan);
				}
			}
		}
	}
	
}
